/*
 * Copyright 2010 Michael Nitsche
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.mnit.basis.swt.element.steuer.rollbar.gruppe.tabelle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import de.mnit.basis.daten.WandleFolge;
import de.mnit.basis.daten.konstant.RECHT;
import de.mnit.basis.daten.struktur.container.Kiste;
import de.mnit.basis.daten.struktur.gruppe.Gruppe3;
import de.mnit.basis.daten.struktur.liste.Liste;
import de.mnit.basis.daten.struktur.liste.S_Liste;
import de.mnit.basis.fehler.Fehler;
import de.mnit.basis.swt.element.feld.SWT_TabellenSpalte;
import de.mnit.basis.swt.element.steuer.rollbar.gruppe.A_SWT_Gruppe;
import de.mnit.basis.swt.statisch.TasteSWT;
import de.mnit.basis.sys.Ausgabe;
import de.mnit.basis.sys.event.S_Zuhoerer;

/**
 * @author Michael Nitsche
 */
public abstract class A_SWT_Tabelle<T extends A_SWT_Tabelle<?>> extends A_SWT_Gruppe<T,Table> {

	private int auswahltyp;
	private boolean zeige_kopf=true;
	private boolean zeilen_kontrast=true;


	public A_SWT_Tabelle() {
		this.auswahltyp=SWT.SINGLE;
		s1_Rahmen(true);
	}


	// FUNKTION

	public T s1_KeinZeilenkopf() {
		this.zeige_kopf=false;
		return t;
	}

	public T s1_KeinZeilenkontrast() {
		this.zeilen_kontrast=false;
		return t;
	}

	public T s1_Mehrfachauswahl() {
		this.auswahltyp=SWT.MULTI;
		return t;
	}

	public T s1_TickBox() {
		this.s1_Style(SWT.CHECK);
		return t;
	}

	public void bauen(boolean sortierbar, boolean verschiebbar, String... titel) {
		Fehler.objekt.wenn_Null((Object)titel);
		for(String t : titel) Fehler.objekt.wenn_Null(t,3);
		if(gBreite()>0) {
			for(int sp=1; sp<=titel.length; sp++) {
				String name=titel[sp-1];
				SWT_TabellenSpalte spalte = sp<=gBreite() ? gSpalte(sp).sText(name) : nTabellenSpalte(name);
				if(sortierbar)   spalte.sSortierbar();
				if(verschiebbar) spalte.sVerschiebbar();
			}
			if(gBreite()>titel.length)
				for(int sp=gBreite(); sp>titel.length; sp--) spalteMinus(sp);
		}
		else
			for(String name : titel) {
				SWT_TabellenSpalte spalte=this.nTabellenSpalte(name);
				if(sortierbar)   spalte.sSortierbar();
				if(verschiebbar) spalte.sVerschiebbar();
			}
	}

	public void spalteMinus(int spalte) {
		Fehler.zahl.wenn_Ausserhalb(1,this.gBreite(),spalte);
		this.gSpalte(spalte).freigeben();
	}

	public abstract void sortieren(int tspalte, boolean absteigend);

	public void spaltenEditierbar(final int[] spalten, final S_Zuhoerer<Gruppe3<Integer, Integer, String>> geaendert_xyt) {
		Fehler.objekt.wenn_Null(spalten, geaendert_xyt);
		Fehler.zahl.wenn_ZuKlein(1, spalten.length);

		final Table tabelle=this.swt();
		final TableEditor editor = new TableEditor(tabelle);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;
		editor.minimumWidth = 50;
		final Kiste<Integer> klickspalte=Kiste.neu(RECHT.SCHREIBEN);

		tabelle.addListener(SWT.MouseDown, new Listener() {
			public void handleEvent (Event event) {
				if(t.gLaenge()==0)
					return;

				// Normalerweise sollte dies mit gZeilenNrBeiAbsPos funzen, tut es aber nicht!
				Point punkt = new Point(event.x, event.y);
				TableItem zeile = tabelle.getItem(tabelle.getTopIndex());
				for(int spalte=0; spalte < tabelle.getColumnCount(); spalte++) {
					Rectangle feldbereich = zeile.getBounds(spalte);
					if(feldbereich.x <= punkt.x && feldbereich.x+feldbereich.width >= punkt.x) {
						spalte++;
						for(int i : spalten)
							if(i==spalte) {
								klickspalte.s(spalte);
								Ausgabe.debug(klickspalte.g(),spalten);
								return;
							}
						klickspalte.s(null);
						return;
					}
				}
			}
		});

		tabelle.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				Control control_alt = editor.getEditor();
				if(control_alt != null)
					control_alt.dispose();
				if(klickspalte.g()==null)
					return;

				final TableItem item = (TableItem)e.item;
				if(item == null) {
					Ausgabe.debug("Kein Item bekommen");
					return;
				}

				Text editor_neu = new Text(tabelle, SWT.NONE);
				editor_neu.setText(item.getText(klickspalte.g()-1));
//				editor_neu.addModifyListener(new ModifyListener() {
//					public void modifyText(ModifyEvent me) {
//						Text text = (Text)editor.getEditor();
//						editor.getItem().setText(klickspalte, text.getText());
//						Ausgabe.debug("Spalte "+klickspalte,"Zeile "+tabelle.indexOf(item),text.getText());
//						k_Tabelle.sFeld(klickspalte+1,tabelle.indexOf(item)+1,text.getText());
//
//						Ausgabe.text(k_Tabelle.gInhalt().gib(klickspalte+1, tabelle.indexOf(item)+1));
//					}
//				});
				editor_neu.selectAll();
				editor_neu.setFocus();
				editor.setEditor(editor_neu, item, klickspalte.g()-1);
				int zeile=tabelle.indexOf(item)+1;
				editor_neu.setData(zeile);

				editor_neu.addListener(SWT.KeyUp, new Listener(){
					public void handleEvent(Event event) {
						if(!TasteSWT.istReturn(event))
							return;
						editorSchliessen(tabelle, editor, klickspalte.g(), geaendert_xyt);
					}
				});
			}
		});

		tabelle.addListener(SWT.MouseMove, new Listener(){
			public void handleEvent(Event event) {
				Point mauspos = new Point(event.x, event.y);
				TableItem zeile=editor.getItem();
				if(zeile==null || zeile.isDisposed())
					return;
				Rectangle feldrahmen = zeile.getBounds(editor.getColumn());
				if(feldrahmen.contains(mauspos))
					return;
				editorSchliessen(tabelle, editor, klickspalte.g(), geaendert_xyt);
			}
		});
	}

	public void editorSchliessen(Table tabelle, TableEditor editor, Integer klickspalte, S_Zuhoerer<Gruppe3<Integer, Integer, String>> geaendert_xyt) {
		Control oldEditor = editor.getEditor();
		if(oldEditor == null || oldEditor.isDisposed())
			return;
		if(klickspalte==null)
			return;

		Text text = (Text)editor.getEditor();
		int tspalte=klickspalte;
		int tzeile =(Integer)editor.getEditor().getData();

		geaendert_xyt.verarbeite(Gruppe3.neu(tspalte, tzeile, text.getText()));
		oldEditor.dispose();
	}


//	public void sTickAuswahl(int zeile, boolean ausgewaehlt) {
//		swt().getItem(zeile-1).setChecked(ausgewaehlt);
//	}

	// LESEN

	public int[] gAuswahlIndex() {
		int[] erg=swt().getSelectionIndices();
		for(int i=0; i<erg.length; i++)
			erg[i]++;
		return erg;
	}

	public int gBreite() {
		return swt().getColumnCount();
	}

	public int gLaenge() {
		return swt().getItemCount();
	}

	public int gSpaltenAnzahl() {
		return swt().getColumnCount();
	}

	public boolean gTickAuswahl(int zeile) {
		return swt().getItem(zeile-1).getChecked();
	}

	public int[] gTickAuswahl() {
		S_Liste<Integer> auswahl=Liste.neu();
		for(int z=1; z<=this.gLaenge(); z++)
			if(this.gTickAuswahl(z))
				auswahl.plus(z);
		return WandleFolge.zuIntArray(auswahl);
	}

	public SWT_TabellenSpalte gSpalte(int spalte) {
		return (SWT_TabellenSpalte)swt().getColumn(spalte-1).getData();
	}

	public S_Liste<SWT_TabellenSpalte> gSpalten() {
		TableColumn[] spalten=swt().getColumns();
		S_Liste<SWT_TabellenSpalte> erg=Liste.neu();
		for(TableColumn c : spalten)
			erg.plus((SWT_TabellenSpalte)c.getData());
		return erg;
	}

	public int gZeilenNr(TableItem ti) {
		Fehler.objekt.wenn_Null(ti);
		return swt().indexOf(ti)+1;
	}

	public int gZeilenNr(Event event) {
		return gZeilenNr((TableItem)event.item);
	}

	public Integer gZeilenNrBeiAbsPos(int x, int y) {
		Point r=this.swt().toDisplay(0,0);
		TableItem ti=swt().getItem(new Point(x-r.x,y-r.y));
		if(ti==null)
			Ausgabe.debug("ist null",x,y,r.x,r.y);
		return ti==null ? null : gZeilenNr(ti);
	}

	// EVENT

	public void eHoleFeldgroesse(Listener aktion) {
		this.swt().addListener(SWT.MeasureItem, aktion);
	}

	public void eFeldZeichnen(Listener aktion) {
		this.swt().addListener(SWT.PaintItem, aktion);
	}

	public void eTickAuswahl(final Listener aktion) {
		this.swt().addListener(SWT.Selection,new Listener(){
			public void handleEvent(Event event) {
				if(event.detail == SWT.CHECK)
					aktion.handleEvent(event);
			}
		});
	}

	// NEU

	public SWT_TabellenSpalte nTabellenSpalte(String text) {
		SWT_TabellenSpalte spalte=new SWT_TabellenSpalte(this,text);
		spalte.erzeugeSWT(swt());
		return spalte;
	}

	// ERZEUGEN

	protected int style5() {
		return style6() | this.auswahltyp | SWT.FULL_SELECTION;
	}

	protected abstract int style6();

	protected Table roh(Composite basis, int style) {
		return new Table(basis,style);
	}

	protected void init5() {
		swt().setHeaderVisible(this.zeige_kopf);
		swt().setLinesVisible(this.zeilen_kontrast);
	}

}
